import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class ReflectMain {

    public static void main(String[] args) throws Exception {
        String packageName = "org.fromsko.dev";
        String classDir = "/Users/fromsko/Desktop/javaBase/course/exp01/target/classes/"
                + packageName.replace('.', '/');
        File dir = new File(classDir);
        if (!dir.exists() || !dir.isDirectory()) {
            System.out.println("目录不存在: " + dir.getAbsolutePath());
            return;
        }
        URL url = new File("./target/classes/").toURI().toURL();
        try (URLClassLoader loader = new URLClassLoader(new URL[] { url })) {
            scanAndInvoke(dir, packageName, loader);
        }
    }

    /**
     * 扫描目录下所有class文件并调用sayHello方法
     */
    private static void scanAndInvoke(File dir, String packageName, ClassLoader loader) {
        File[] files = dir.listFiles((d, name) -> name.endsWith(".class"));
        if (files == null)
            return;
        for (File file : files) {
            String className = packageName + "." + file.getName().replace(".class", "");
            try {
                Class<?> clazz = loader.loadClass(className);
                if (isConcreteClass(clazz) && implementsMyService(clazz, loader)) {
                    invokeSayHello(clazz);
                }
            } catch (Exception e) {
                System.out.println("加载或调用失败: " + className + ", 错误: " + e.getMessage());
            }
        }
    }

    /**
     * 判断是否为具体类（非接口、非抽象类）
     */
    private static boolean isConcreteClass(Class<?> clazz) {
        int mod = clazz.getModifiers();
        return !clazz.isInterface() && !java.lang.reflect.Modifier.isAbstract(mod);
    }

    /**
     * 反射调用sayHello方法
     */
    private static void invokeSayHello(Class<?> clazz) {
        try {
            Object obj = clazz.getDeclaredConstructor().newInstance();
            Method method = clazz.getMethod("sayHello");
            method.invoke(obj);
        } catch (NoSuchMethodException e) {
            System.out.println(clazz.getName() + " 没有 sayHello 方法");
        } catch (Exception e) {
            System.out.println(clazz.getName() + " 调用 sayHello 失败: " + e.getMessage());
        }
    }

    /**
     * 判断clazz是否实现了MyService接口
     */
    private static boolean implementsMyService(Class<?> clazz, ClassLoader loader) {
        try {
            Class<?> myService = loader.loadClass("org.fromsko.dev.MyService");
            return myService.isAssignableFrom(clazz) && !clazz.equals(myService);
        } catch (Exception e) {
            return false;
        }
    }
}
